package hudson.plugins.templateproject;
import hudson.Extension;
import hudson.Launcher;
import hudson.console.HyperlinkNote;
import hudson.matrix.MatrixProject;
import hudson.model.AbstractBuild;
import hudson.model.AbstractProject;
import hudson.model.Action;
import hudson.model.BuildListener;
import jenkins.model.DependencyDeclarer;
import hudson.model.DependencyGraph;
import hudson.model.Hudson;
import hudson.model.Item;
import hudson.model.Project;
import hudson.model.Run;
import hudson.security.AccessControlled;
import hudson.tasks.BuildWrapper;
import hudson.tasks.BuildWrapperDescriptor;
import hudson.tasks.Messages;
import hudson.util.FormValidation;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.kohsuke.stapler.AncestorInPath;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
public class ProxyBuildEnvironment extends BuildWrapper implements DependencyDeclarer {
private final String projectName;
@DataBoundConstructor
public ProxyBuildEnvironment(String projectName) {
this.projectName = projectName;
}
public String getProjectName() {
return projectName;
}
public String getExpandedProjectName(AbstractBuild<?, ?> build) {
return TemplateUtils.getExpandedProjectName(projectName, build);
}
public AbstractProject<?, ?> getProject() {
return TemplateUtils.getProject(projectName, null);
}
public List<BuildWrapper> getProjectBuildWrappers(AbstractBuild<?, ?> build) {
AbstractProject p = TemplateUtils.getProject(getProjectName(), build);
if (p instanceof Project) {
return ((Project) p).getBuildWrappersList();
} else if (p instanceof MatrixProject) {
return ((MatrixProject) p).getBuildWrappersList();
} else {
return Collections.emptyList();
}
}
@Override
public final void buildDependencyGraph(final AbstractProject project, final DependencyGraph graph) {
final Item item = Hudson.getInstance().getItemByFullName(getProjectName());
AbstractProject<?, ?> templateProject = (AbstractProject) Hudson.getInstance().getItem(getProjectName());
if (item instanceof Project) {
// @TODO : see how important it is that this gets expanded projectName
for (BuildWrapper wrapper : getProjectBuildWrappers(null)) {
if (wrapper instanceof DependencyDeclarer) {
((DependencyDeclarer) wrapper).buildDependencyGraph(project, graph);
}
}
}
}
@Override
public Environment setUp(@SuppressWarnings("rawtypes") AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException,
InterruptedException {
AbstractProject p = TemplateUtils.getProject(getProjectName(), build);
listener.getLogger().println("[TemplateProject] Getting environment from: " + HyperlinkNote.encodeTo('/'+ p.getUrl(), p.getFullDisplayName()));
for (BuildWrapper builder : getProjectBuildWrappers(build)) {
builder.setUp(build, launcher, listener);
}
listener.getLogger().println("[TemplateProject] Successfully setup environment from: '" + p.getFullDisplayName() + "'");
return new Environment() {
@Override
public boolean tearDown(@SuppressWarnings("rawtypes") AbstractBuild build, BuildListener listener) throws IOException, InterruptedException {
// let build continue
return true;
}
};
}
@Override
public void preCheckout(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException {
AbstractProject p = TemplateUtils.getProject(getProjectName(), build);
listener.getLogger().println("[TemplateProject] Starting pre-checkout from: " + HyperlinkNote.encodeTo('/'+ p.getUrl(), p.getFullDisplayName()));
for (BuildWrapper builder : getProjectBuildWrappers(build)) {
builder.preCheckout(build, launcher, listener);
}
listener.getLogger().println("[TemplateProject] Successfully performed pre-checkout from: '" + p.getFullDisplayName() + "'");
}
@Override
public Launcher decorateLauncher(AbstractBuild build, Launcher launcher, BuildListener listener) throws IOException, InterruptedException, Run.RunnerAbortedException {
for (BuildWrapper builder : getProjectBuildWrappers(build)) {
launcher = builder.decorateLauncher(build, launcher, listener);
}
return launcher;
}
@Override
public OutputStream decorateLogger(AbstractBuild build, OutputStream logger) throws IOException, InterruptedException, Run.RunnerAbortedException {
for (BuildWrapper builder : getProjectBuildWrappers(build)) {
logger = builder.decorateLogger(build, logger);
}
return logger;
}
@Extension
public static class DescriptorImpl extends BuildWrapperDescriptor {
@Override
public String getDisplayName() {
return "Use build environment from another project";
}
@Override
public boolean isApplicable(AbstractProject<?, ?> jobType) {
return true;
}
/**
* Form validation method.
*/
public FormValidation doCheckProjectName(@AncestorInPath AccessControlled anc, @QueryParameter String value) {
// Require CONFIGURE permission on this project
if (!anc.hasPermission(Item.CONFIGURE)) {
return FormValidation.ok();
}
Item item = Hudson.getInstance().getItemByFullName(
value, Item.class);
if (item == null) {
return FormValidation.error(Messages.BuildTrigger_NoSuchProject(value,
AbstractProject.findNearest(value)
.getName()));
}
if (!(item instanceof Project) && !(item instanceof MatrixProject)) {
return FormValidation.error(Messages.BuildTrigger_NotBuildable(value));
}
return FormValidation.ok();
}
}
@Override
public Collection<? extends Action> getProjectActions(AbstractProject project) {
List<Action> actions = new ArrayList<Action>();
// @TODO : see how important it is that this gets expanded projectName
for (BuildWrapper wrapper : getProjectBuildWrappers(null)) {
actions.addAll(wrapper.getProjectActions(project));
}
return actions;
}
}